package com.netnovelstore.service.impl;

import com.netnovelstore.dao.BookMapper;
import com.netnovelstore.pojo.BookContent;
import com.netnovelstore.service.AsyncService;
import com.netnovelstore.util.Resolver;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.session.ExecutorType;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.util.List;
import java.util.concurrent.CountDownLatch;

@Service
@Slf4j
public class AsyncServiceImpl implements AsyncService {

    @Value("${web.book-path}")
    private String bookPath;

    private SqlSessionFactory sqlSessionFactory;
    private Resolver resolver;

    @Autowired
    public AsyncServiceImpl(SqlSessionFactory sqlSessionFactory, Resolver resolver) {
        this.sqlSessionFactory = sqlSessionFactory;
        this.resolver = resolver;
    }

    @Override
    @Async("taskExecutor")
    public void asyncBatchInsertBookContent(CountDownLatch countDownLatch, Integer bookNumber, String bookName) {
        try {
            log.warn("start Batch Insert");
            resolver.setFilePath(bookPath);
            List<BookContent> bookContentList = resolver.ProcessNovelByBookNumber(bookNumber, bookName);
            add(bookContentList);
            log.warn("end Batch Insert");
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            // 很关键, 无论上面程序是否异常必须执行countDown,否则await无法释放
            countDownLatch.countDown();
        }
    }

    @Transactional
    public void add(List<BookContent> itemList) {
        SqlSession session = sqlSessionFactory.openSession(ExecutorType.BATCH, false);
        BookMapper mapper = session.getMapper(BookMapper.class);
        int count = 0;
        for (BookContent book : itemList) {

            mapper.insertBookTo_tb_novel_contentByForeach(book);
            if (count % 1000 == 999) {//每1000条提交一次防止内存溢出
                session.commit();
                session.clearCache();
            }
            count++;
        }
        session.commit();
        session.clearCache();

    }
}
